home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 192_01 / bawkdo.c < prev    next >
Text File  |  1980-01-01  |  13KB  |  768 lines

  1. /*
  2.  * Bawk C actions interpreter
  3.  */
  4. #include <stdio.h>
  5. #include "bawk.h"
  6.  
  7. dopattern( pat )
  8. char *pat;
  9. {
  10.     Where = PATTERN;
  11.     Actptr = pat;
  12.     getoken();
  13.     expression();
  14.     return popint();
  15. }
  16.  
  17. doaction( act )
  18. char *act;
  19. {
  20.     Where = ACTION;
  21.     Actptr = act;
  22.     getoken();
  23.     while ( Token!=T_EOF )
  24.         statement();
  25. }
  26.  
  27. expression()
  28. {
  29.     expr1();
  30.  
  31.     if ( Token==T_ASSIGN )
  32.     {
  33.         getoken();
  34.         assignment( expression() );
  35.     }
  36. }
  37.  
  38. expr1()
  39. {
  40.     int ival;
  41.  
  42.     expr2();
  43.     for ( ;; )
  44.     {
  45.         if ( Token==T_LIOR )
  46.         {
  47.             getoken();
  48.             ival = popint();
  49.             expr2();
  50.             pushint( popint() || ival );
  51.         }
  52.         else
  53.             return;
  54.     }
  55. }
  56.  
  57. expr2()
  58. {
  59.     int ival;
  60.  
  61.     expr3();
  62.     for ( ;; )
  63.     {
  64.         if ( Token==T_LAND )
  65.         {
  66.             getoken();
  67.             ival = popint();
  68.             expr3();
  69.             pushint( popint() && ival );
  70.         }
  71.         else
  72.             return;
  73.     }
  74. }
  75.  
  76. expr3()
  77. {
  78.     int ival;
  79.  
  80.     expr4();
  81.     for ( ;; )
  82.     {
  83.         if ( Token==T_IOR )
  84.         {
  85.             getoken();
  86.             ival = popint();
  87.             expr4();
  88.             pushint( popint() | ival );
  89.         }
  90.         else
  91.             return;
  92.     }
  93. }
  94.  
  95.  
  96. expr4()
  97. {
  98.     int ival;
  99.  
  100.     expr5();
  101.     for ( ;; )
  102.     {
  103.         if ( Token==T_AND )
  104.         {
  105.             getoken();
  106.             ival = popint();
  107.             expr5();
  108.             pushint( popint() & ival );
  109.         }
  110.         else
  111.             return;
  112.     }
  113. }
  114.  
  115. expr5()
  116. {
  117.     int ival;
  118.  
  119.     expr6();
  120.     for ( ;; )
  121.     {
  122.         if ( Token==T_XOR )
  123.         {
  124.             getoken();
  125.             ival = popint();
  126.             expr6();
  127.             pushint( popint() ^ ival );
  128.         }
  129.         else
  130.             return;
  131.     }
  132. }
  133.  
  134. expr6()
  135. {
  136.     int ival;
  137.  
  138.     expr7();
  139.     for ( ;; )
  140.     {
  141.         if ( Token==T_EQ )
  142.         {
  143.             getoken();
  144.             ival = popint();
  145.             expr7();
  146.             pushint( ival == popint() );
  147.         }
  148.         else if ( Token==T_NE )
  149.         {
  150.             getoken();
  151.             ival = popint();
  152.             expr7();
  153.             pushint( ival != popint() );
  154.         }
  155.         else
  156.             return;
  157.     }
  158. }
  159.  
  160. expr7()
  161. {
  162.     int ival;
  163.  
  164.     expr8();
  165.     for ( ;; )
  166.     {
  167.         if ( Token==T_LE )
  168.         {
  169.             getoken();
  170.             ival = popint();
  171.             expr8();
  172.             pushint( ival <= popint() );
  173.         }
  174.         else if ( Token==T_GE )
  175.         {
  176.             getoken();
  177.             ival = popint();
  178.             expr8();
  179.             pushint( ival >= popint() );
  180.         }
  181.         else if ( Token==T_LT )
  182.         {
  183.             getoken();
  184.             ival = popint();
  185.             expr8();
  186.             pushint( ival < popint() );
  187.         }
  188.         else if ( Token==T_GT )
  189.         {
  190.             getoken();
  191.             ival = popint();
  192.             expr8();
  193.             pushint( ival > popint() );
  194.         }
  195.         else
  196.             return;
  197.     }
  198. }
  199.  
  200. expr8()
  201. {
  202.     int ival;
  203.  
  204.     expr9();
  205.     for ( ;; )
  206.     {
  207.         if ( Token==T_SHL )
  208.         {
  209.             getoken();
  210.             ival = popint();
  211.             expr9();
  212.             pushint( ival << popint() );
  213.         }
  214.         else if ( Token==T_SHR )
  215.         {
  216.             getoken();
  217.             ival = popint();
  218.             expr9();
  219.             pushint( ival >> popint() );
  220.         }
  221.         else
  222.             return;
  223.     }
  224. }
  225.  
  226. expr9()
  227. {
  228.     int ival;
  229.  
  230.     expr10();
  231.     for ( ;; )
  232.     {
  233.         if ( Token==T_ADD )
  234.         {
  235.             getoken();
  236.             ival = popint();
  237.             expr10();
  238.             pushint( ival + popint() );
  239.         }
  240.         else if ( Token==T_SUB )
  241.         {
  242.             getoken();
  243.             ival = popint();
  244.             expr10();
  245.             pushint( ival - popint() );
  246.         }
  247.         else
  248.             return;
  249.     }
  250. }
  251.  
  252. expr10()
  253. {
  254.     int ival;
  255.  
  256.     primary();
  257.     for ( ;; )
  258.     {
  259.         if ( Token==T_MUL )
  260.         {
  261.             getoken();
  262.             ival = popint();
  263.             primary();
  264.             pushint( ival * popint() );
  265.         }
  266.         else if ( Token==T_DIV )
  267.         {
  268.             getoken();
  269.             ival = popint();
  270.             primary();
  271.             pushint( ival / popint() );
  272.         }
  273.         else if ( Token==T_MOD )
  274.         {
  275.             getoken();
  276.             ival = popint();
  277.             primary();
  278.             pushint( ival % popint() );
  279.         }
  280.         else
  281.             return;
  282.     }
  283. }
  284.  
  285. primary()
  286. {
  287.     int index;
  288.     DATUM data;
  289.     VARIABLE *pvar;
  290.  
  291.     switch ( Token )
  292.     {
  293.     case T_LPAREN:
  294.         /*
  295.          * it's a parenthesized expression
  296.          */
  297.         getoken();
  298.         expression();
  299.         if ( Token!=T_RPAREN )
  300.             error( "missing ')'", ACT_ERROR );
  301.         getoken();
  302.         break;
  303.     case T_LNOT:
  304.         getoken();
  305.         primary();
  306.         pushint( ! popint() );
  307.         break;
  308.     case T_NOT:
  309.         getoken();
  310.         primary();
  311.         pushint( ~ popint() );
  312.         break;
  313.     case T_ADD:
  314.         getoken();
  315.         primary();
  316.         break;
  317.     case T_SUB:
  318.         getoken();
  319.         primary();
  320.         pushint( - popint() );
  321.         break;
  322.     case T_INCR:
  323.     case T_DECR:
  324.         preincdec();
  325.         break;
  326.     case T_MUL:
  327.         getoken();
  328.         primary();
  329.         /*
  330.          * If item on stack is an LVALUE, do an extra level of
  331.          * indirection before changing it to an LVALUE.
  332.          */
  333.         if ( Stackptr->lvalue )
  334.             Stackptr->value.ptrptr = *Stackptr->value.ptrptr;
  335.         Stackptr->lvalue = 1;
  336.         --Stackptr->class;
  337.         break;
  338.     case T_AND:
  339.         getoken();
  340.         primary();
  341.         if ( Stackptr->lvalue )
  342.             Stackptr->lvalue = 0;
  343.         else
  344.             error( "'&' operator needs an lvalue", ACT_ERROR );
  345.         break;
  346.     case T_CONSTANT:
  347.         pushint( Value.ival );
  348.         getoken();
  349.         break;
  350.     case T_REGEXP:
  351.         /*
  352.          * It's a regular expression - parse it and compile it.
  353.          */
  354.         if ( Where == PATTERN )
  355.         {
  356.             /*
  357.              * We're processing a pattern right now - perform a
  358.              * match of the regular expression agains input line.
  359.              */
  360.             unparse( Fields, Fieldcount, Linebuf, Fieldsep );
  361.             pushint( match( Linebuf, Value.dptr ) );
  362.         }
  363.         else
  364.             push( 1, ACTUAL, BYTE, &Value );
  365.         getoken();
  366.         break;
  367.     case T_NF:
  368.         pushint( Fieldcount );
  369.         getoken();
  370.         break;
  371.     case T_NR:
  372.         pushint( Recordcount );
  373.         getoken();
  374.         break;
  375.     case T_FS:
  376.         Fieldsep[1] = 0;
  377.         data.dptr = Fieldsep;
  378.         push( 0, LVALUE, BYTE, &data );
  379.         getoken();
  380.         break;
  381.     case T_RS:
  382.         Recordsep[1] = 0;
  383.         data.dptr = Recordsep;
  384.         push( 0, LVALUE, BYTE, &data );
  385.         getoken();
  386.         break;
  387.     case T_FILENAME:
  388.         data.dptr = Filename;
  389.         push( 1, ACTUAL, BYTE, &data );
  390.         getoken();
  391.         break;
  392.     case T_DOLLAR:
  393.         /*
  394.          * It's a reference to one (or all) of the words in Linebuf.
  395.          */
  396.         getoken();
  397.         primary();
  398.         if ( index = popint() )
  399.         {
  400.             if ( index > Fieldcount )
  401.                 index = Fieldcount;
  402.             else if ( index < 1 )
  403.                 index = 1;
  404.             data.dptr = Fields[ index-1 ];
  405.         }
  406.         else
  407.         {
  408.             /*
  409.              * Reconstitute the line buffer in case any of the
  410.              * fields have been changed.
  411.              */
  412.             unparse( Fields, Fieldcount, Linebuf, Fieldsep );
  413.             data.dptr = Linebuf;
  414.         }
  415.         /*
  416.          * $<expr>'s are treated the same as string constants:
  417.          */
  418.         push( 1, ACTUAL, BYTE, &data );
  419.         break;
  420.     case T_STRING:
  421.         push( 1, ACTUAL, BYTE, &Value );
  422.         getoken();
  423.         break;
  424.     case T_FUNCTION:
  425.         /*
  426.          * Do a built-in function call
  427.          */
  428.         index = Value.ival;
  429.         getoken();
  430.         function( index );
  431.         break;
  432.     case T_VARIABLE:
  433.         pvar = Value.dptr;
  434.         getoken();
  435.         /*
  436.          * it's a plain variable. The way a variable is
  437.          * represented on the stack depends on its type:
  438.          *      lvalue class value.dptr
  439.          * vars:  1      0   address of var
  440.          * ptrs:  1      1   ptr to address of ptr
  441.          * array: 0      1   address of var
  442.          */
  443.         if ( pvar->vclass && !pvar->vlen )
  444.             /* it's a pointer */
  445.             data.dptr = &pvar->vptr;
  446.         else
  447.             /* an array or simple variable */
  448.             data.dptr = pvar->vptr;
  449.         /*
  450.          * If it's an array it can't be used as an LVALUE.
  451.          */
  452.         push( pvar->vclass, !pvar->vlen, pvar->vsize, &data );
  453.         break;
  454.     case T_EOF:
  455.         break;
  456.     default:
  457.         syntaxerror();
  458.     }
  459.     /*
  460.      * a "[" means it's an array reference
  461.      */
  462.     if ( Token==T_LBRACKET )
  463.     {
  464.         getoken();
  465.         if ( ! Stackptr->class )
  466.             error( "'[]' needs an array or pointer", ACT_ERROR );
  467.         /*
  468.          * compute the subscript
  469.          */
  470.         expression();
  471.         if ( Token!=T_RBRACKET )
  472.             error( "missing ']'", ACT_ERROR );
  473.         getoken();
  474.         index = popint();
  475.         /*
  476.          * compute the offset (subscript times two for int arrays)
  477.          * and then the effective address.
  478.          */
  479.         index *= Stackptr->size;
  480.         if ( Stackptr->lvalue )
  481.             /*
  482.              * It's a pointer - don't forget that the stack top
  483.              * item's value is the address of the pointer so we
  484.              * must do another level of indirection.
  485.              */
  486.             Stackptr->value.dptr = *Stackptr->value.ptrptr+index;
  487.         else
  488.             /*
  489.              * It's a plain array - the stack top item's value is
  490.              * the address of the first element in the array.
  491.              */
  492.             Stackptr->value.dptr += index;
  493.  
  494.         /*
  495.          * The stack top item now becomes an LVALUE, but we've
  496.          * reduced the indirection level.
  497.          */
  498.         Stackptr->lvalue = 1;
  499.         --Stackptr->class;
  500.     }
  501.  
  502.     if ( Token==T_INCR || Token==T_DECR )
  503.         postincdec();
  504. }
  505.  
  506. preincdec()
  507. {
  508.     /*
  509.      * Pre increment/decrement
  510.      */
  511.     int incr;
  512.  
  513.     incr = Token==T_INCR ? 1 : -1;
  514.     getoken();
  515.     primary(